package com.epam.cdp.selenium2.core.runner.cli;

import org.apache.commons.lang.RandomStringUtils;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.OptionDef;
import org.kohsuke.args4j.spi.OptionHandler;
import org.kohsuke.args4j.spi.Parameters;
import org.kohsuke.args4j.spi.Setter;

import com.epam.cdp.selenium2.core.common.SpecialSymbols;
import com.epam.cdp.selenium2.core.configuration.SeleniumInstanceConfiguration;
import com.epam.cdp.selenium2.core.exception.UnsupportedDriverTypeException;
import com.epam.cdp.selenium2.core.results.logger.Logger;
import com.epam.cdp.selenium2.core.ui.WebDriverType;

/**
 * Handler for SeleniumRC CLI parameter. Option has format <b>name#login:password@hostname:port//browser</b>.<br>
 * Login and password(or just password), port may absent. In this case default values will be used.<br>
 * <br>
 * Login and password default value is empty string.<br>
 * Default hostname is <b>localhost</b>.<br>
 * Default port is <b>4444</b>.
 * 
 * @author yyudzitski
 */
public class SeleniumConfigCliHandler extends OptionHandler<SeleniumInstanceConfiguration>
{
  private static final String DEFAULT_HOST_INFO = "localhost:4444//firefox";

  public SeleniumConfigCliHandler( CmdLineParser parser, OptionDef option,
    Setter<? super SeleniumInstanceConfiguration> setter )
  {
    super( parser, option, setter );
  }

  @Override
  public int parseArguments( Parameters params ) throws CmdLineException
  {
    this.setter.addValue( parseArgument( params.getParameter( 0 ) ) );
    return 1;
  }

  @Override
  public String getDefaultMetaVariable()
  {
    return DEFAULT_HOST_INFO;
  }

  private SeleniumInstanceConfiguration parseArgument( String param )
  {
    String optionValue = param;
    String hostVaue;
    SeleniumInstanceConfiguration config = new SeleniumInstanceConfiguration();
    /** Parse browser type */
    if( optionValue.split( SpecialSymbols.SLASH.toString() + SpecialSymbols.SLASH.toString() ).length > 1 )
    {
      try
      {
        config.setDriverType( WebDriverType.getByDriverName( optionValue.split( SpecialSymbols.SLASH.toString()
          + SpecialSymbols.SLASH.toString() )[1] ) );
      }
      catch( UnsupportedDriverTypeException e )
      {
        Logger.error( "Driver type not supported: "
          + optionValue.split( SpecialSymbols.SLASH.toString() + SpecialSymbols.SLASH.toString() )[1]
          + ". Default will be used(firefox)." );
        config.setDriverType( WebDriverType.FIREFOX );
      }
      optionValue = optionValue.split( SpecialSymbols.SLASH.toString() + SpecialSymbols.SLASH.toString() )[0];
    }
    /** Parse configuration name */
    if( optionValue.split( SpecialSymbols.LATTICE.toString() ).length > 1 )
    {
      config.setConfigName( optionValue.split( SpecialSymbols.LATTICE.toString() )[0] );
      hostVaue = optionValue.split( SpecialSymbols.LATTICE.toString() )[1];
    }
    else
    {
      config.setConfigName( RandomStringUtils.randomAlphanumeric( 10 ) );
      hostVaue = optionValue;
    }
    /** Just host info present(For example: -sc localhost:4444) */
    if( hostVaue.split( SpecialSymbols.DOG.toString() ).length == 1 )
    {
      getLoginInfo( config, SpecialSymbols.EMPTY.toString() );
      getHostInfo( config, hostVaue.split( SpecialSymbols.DOG.toString() )[0] );
    }
    /** Full info present(For example: -sc login:pass@localhost:4444) */
    else if( hostVaue.split( SpecialSymbols.DOG.toString() ).length == 2 )
    {
      getLoginInfo( config, hostVaue.split( SpecialSymbols.DOG.toString() )[0] );
      getHostInfo( config, hostVaue.split( SpecialSymbols.DOG.toString() )[1] );
    }
    return config;
  }

  private void getLoginInfo( SeleniumInstanceConfiguration config, String loginInfo )
  {
    /** Just login present */
    if( loginInfo.split( SpecialSymbols.COLON.toString() ).length == 1 )
    {
      config.setHostLogin( loginInfo.split( SpecialSymbols.COLON.toString() )[0] );
      config.setHostPassword( SpecialSymbols.EMPTY.toString() );
    }
    /** Login and password present */
    else if( loginInfo.split( SpecialSymbols.COLON.toString() ).length == 2 )
    {
      config.setHostLogin( loginInfo.split( SpecialSymbols.COLON.toString() )[0] );
      config.setHostPassword( loginInfo.split( SpecialSymbols.COLON.toString() )[1] );
    }
  }

  private void getHostInfo( SeleniumInstanceConfiguration config, String hostInfo )
  {
    /** Just host name present. Default port used(port - 4444). */
    if( hostInfo.split( SpecialSymbols.COLON.toString() ).length == 1 )
    {
      config.setSeleniumHost( hostInfo.split( SpecialSymbols.COLON.toString() )[0] );
      config.setSeleniumPort( DEFAULT_HOST_INFO.split( SpecialSymbols.COLON.toString() )[1] );
    }
    /** Host name with port present. */
    else if( hostInfo.split( SpecialSymbols.COLON.toString() ).length == 2 )
    {
      config.setSeleniumHost( hostInfo.split( SpecialSymbols.COLON.toString() )[0] );
      config.setSeleniumPort( hostInfo.split( SpecialSymbols.COLON.toString() )[1] );
    }
  }
}